AS3 FlexNativeMenu and dataprovider

Yesterday I faced an issue with FlexNativeMenu (popup menu) and its dataprovider. Looks like, FlexNativeMenu does not recognize the changes made to dataprovider.

Situation: I was wanted to disable the menu item based on the Label (clicking which I am showing the FlexNativeMenu as a Popup menu).

So, before showing the menu (FlexNativeMenu.display) I tried to update the Dataprovider (XML). But changes were not reflected in the menu! Further, Error #1009 was reported after clicking any menuItem.

I even tried to assign the dataprovider again hoping that this way problem will get resolved.
But this time also, changes were not reflected. However, Menu was updated after clicking twice on the same label. But clicking on any menuItem was still reporting Error #1009.

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
layout="horizontal" creationComplete="init();">
<mx:Script>
<!&#91;CDATA&#91;
import mx.controls.Alert;
import mx.events.FlexNativeMenuEvent;
import mx.containers.HBox;
import mx.controls.TextInput;
import mx.controls.Label;
import mx.controls.FlexNativeMenu;

private var phoneList:Array;
private var popupMenu:FlexNativeMenu;
private var lblWidth:uint;

private function init():void {
lblWidth = 50;
phoneList = new Array({type:"Home", number:"11111"}, {type:"Work", number:"22222"});
initPopupMenu();
phoneList.forEach(showPhoneList);
}

private function initPopupMenu():void {
popupMenu = new FlexNativeMenu();
popupMenu.dataProvider = defaultPhoneProps;
popupMenu.showRoot = false;
popupMenu.labelField = "@label";
}

private function showPhoneList(item:*, index:int, arr:Array):void {
var phoneLabel:Label = new Label();
var phoneNumber:TextInput = new TextInput();
var hBox:HBox = new HBox();
phoneLabel.id = "label";
phoneLabel.addEventListener(MouseEvent.CLICK, showContextMenu)
phoneLabel.text = item.type;
phoneLabel.width = lblWidth;
phoneNumber.id = "number";
phoneNumber.text = item.number;
hBox.id = "phone_"+item.type;
hBox.addChild(phoneLabel);
hBox.addChild(phoneNumber);
phoneListContainer.addChild(hBox);
}

private function showContextMenu(event:MouseEvent):void {
// Update Dataprovider
// Any changes to the dataprovider result in runtime error:
/*
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at mx.controls::FlexNativeMenu/itemSelectHandler()&#91;E:\dev\3.1.0\frameworks\projects\airframework\src\mx\controls\FlexNativeMenu.as:1633&#93;
at flash.display::NativeMenu/_display()
at flash.display::NativeMenu/display()
at mx.controls::FlexNativeMenu/display()&#91;E:\dev\3.1.0\frameworks\projects\airframework\src\mx\controls\FlexNativeMenu.as:1364&#93;
at NativeMenuTest/showContextMenu()&#91;C:\Users\Tushar\Documents\Flex Builder 3\NativeMenuTest\src\NativeMenuTest.mxml:56&#93;
*/
// For example, you update the dataprovider:
for each (var property:XML in defaultPhoneProps..menuitem) {
property.@toggled = "false";
property.@enabled = "true";
}
defaultPhoneProps..menuitem.(@label==event.currentTarget.text).@toggled = "true";
defaultPhoneProps..menuitem.(@label==event.currentTarget.text).@enabled = "false";
// Show Popup Menu
popupMenu.addEventListener(FlexNativeMenuEvent.ITEM_CLICK, onItemClick);
popupMenu.display(event.target.stage, event.stageX, event.stageY);
}

private function onItemClick(menuEvent:FlexNativeMenuEvent):void{
popupMenu.removeEventListener(FlexNativeMenuEvent.ITEM_CLICK, onItemClick);
//Alert.show(menuEvent.item.@label, "Native Menu Event")
}
&#93;&#93;>
</mx:Script>
<mx:XML id="defaultPhoneProps" format="e4x">
<menu label="Popup">
<menuitem label="Work" command="toggleIconMenu"
type="check" toggled="false" enabled="true"/>
<menuitem label="Home" command="toggleMenuBar"
type="check" toggled="false" enabled="true"/>
<menuitem label="Mobile" command="toggleIconMenu"
type="check" toggled="false" enabled="true"/>
<menuitem label="HomeFax" command="toggleIconMenu"
type="check" toggled="false" enabled="true"/>
<menuitem label="WorkFax" command="toggleIconMenu"
type="check" toggled="false" enabled="true"/>
</menu>
</mx:XML>
<mx:VBox id="phoneListContainer" />
</mx:WindowedApplication>

Solution:
To solve this problem I had to work with the FlexNativeMenuItem directly.
Updated showContextMenu function:

private function showContextMenu(event:MouseEvent):void {
// Update NativeMenuItem directly along with the dataprovider
for each (var property:NativeMenuItem in popupMenu.nativeMenu.items) {
if(property.label == event.currentTarget.text){
property.enabled = false;
property.checked = true;
} else {
property.enabled = true;
property.checked = false;
}
}
// Show Popup
popupMenu.addEventListener(FlexNativeMenuEvent.ITEM_CLICK, onItemClick);
popupMenu.display(event.target.stage, event.stageX, event.stageY);
}

About Tushar

Hi, I am Tushar Wadekar from Pune, India. I am an Adobe Certified Flash Developer. My Interests are: Flash, ActionScript, Flex, AIR, PHP, Ruby on Rails. You can reach me at: tusharwadekar[at]gmail[dot]com Thank you! Tushar
This entry was posted in ActionScript3, AIR, AS3, Flash, Flex. Bookmark the permalink.

Leave a comment